package com.zhentao.engine.impl;

import com.zhentao.dto.RuleExecuteRequestDTO;
import com.zhentao.engine.RuleEngine;
import com.zhentao.engine.RuleEngineManager;
import com.zhentao.enums.RuleExecuteStatusEnum;
import com.zhentao.pojo.ParamRule;
import com.zhentao.service.ParamRuleService;
import com.zhentao.vo.ParamRuleVO;
import com.zhentao.vo.RuleExecuteResultVO;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 规则引擎管理器实现
 * @author zhentao
 * @date 2024-12-19
 */
@Slf4j
@Service
public class RuleEngineManagerImpl implements RuleEngineManager {

    @Autowired
    @Lazy
    private ParamRuleService paramRuleService;

    /**
     * 规则引擎注册表 - key: 引擎类型, value: 引擎实例
     */
    private final Map<String, RuleEngine> engineRegistry = new ConcurrentHashMap<>();

    /**
     * 规则执行缓存 - key: 缓存键, value: 执行结果
     */
    private final Map<String, CacheEntry> executionCache = new ConcurrentHashMap<>();

    /**
     * 缓存项
     */
    private static class CacheEntry {
        private final RuleExecuteResultVO result;
        private final long expireTime;

        public CacheEntry(RuleExecuteResultVO result, long ttl) {
            this.result = result;
            this.expireTime = System.currentTimeMillis() + ttl * 1000;
        }

        public boolean isExpired() {
            return System.currentTimeMillis() > expireTime;
        }

        public RuleExecuteResultVO getResult() {
            return result;
        }
    }

    @PostConstruct
    public void initEngines() {
        log.info("初始化规则引擎管理器...");
        
        // 注册内置规则引擎
        registerEngine(new GroovyRuleEngine());
        registerEngine(new RegexRuleEngine());
        registerEngine(new SpELRuleEngine());
        
        log.info("规则引擎管理器初始化完成，已注册引擎数量: {}", engineRegistry.size());
    }

    @Override
    public RuleExecuteResultVO executeRule(RuleExecuteRequestDTO request) {
        Date startTime = new Date();
        String traceId = generateTraceId();
        
        try {
            // 参数校验
            if (!StringUtils.hasText(request.getRuleCode())) {
                return createErrorResult(request.getRuleCode(), null, 
                    RuleExecuteStatusEnum.PARAM_ERROR, "规则编码不能为空", startTime, traceId, request);
            }

            // 获取规则信息
            ParamRuleVO ruleVO = paramRuleService.getRuleDetailByCode(request.getRuleCode());
            if (ruleVO == null) {
                return createErrorResult(request.getRuleCode(), null,
                    RuleExecuteStatusEnum.NOT_FOUND, "规则不存在: " + request.getRuleCode(), startTime, traceId, request);
            }

            // 检查规则状态
            if (ruleVO.getStatus() != 1) {
                return createErrorResult(request.getRuleCode(), ruleVO.getRuleName(),
                    RuleExecuteStatusEnum.DISABLED, "规则已禁用", startTime, traceId, request);
            }

            // 检查缓存
            if (Boolean.TRUE.equals(request.getUseCache()) && ruleVO.getCacheResult() == 1) {
                String cacheKey = generateCacheKey(request);
                CacheEntry cacheEntry = executionCache.get(cacheKey);
                if (cacheEntry != null && !cacheEntry.isExpired()) {
                    RuleExecuteResultVO cachedResult = cloneResult(cacheEntry.getResult());
                    cachedResult.setUsedCache(true);
                    cachedResult.setCacheKey(cacheKey);
                    cachedResult.setTraceId(traceId);
                    log.debug("规则执行命中缓存: {}", request.getRuleCode());
                    return cachedResult;
                }
            }

            // 转换为ParamRule对象（简化实现）
            ParamRule rule = convertToParamRule(ruleVO);
            
            // 执行规则
            return executeRule(rule, request);

        } catch (Exception e) {
            log.error("规则执行异常: {}", request.getRuleCode(), e);
            return createErrorResult(request.getRuleCode(), null,
                RuleExecuteStatusEnum.ERROR, "规则执行异常: " + e.getMessage(), startTime, traceId, request);
        }
    }

    @Override
    public RuleExecuteResultVO executeRule(ParamRule rule, RuleExecuteRequestDTO request) {
        Date startTime = new Date();
        String traceId = generateTraceId();
        
        try {
            // 获取规则引擎类型（从规则内容中推断，简化实现）
            String engineType = inferEngineType(rule);
            
            // 获取对应的规则引擎
            RuleEngine engine = engineRegistry.get(engineType);
            if (engine == null) {
                return createErrorResult(rule.getRuleCode(), rule.getRuleName(),
                    RuleExecuteStatusEnum.ERROR, "不支持的规则引擎类型: " + engineType, startTime, traceId, request);
            }

            // 执行规则
            RuleExecuteResultVO result = engine.executeRule(rule, request.getInputData(), request.getContext());
            
            // 设置执行信息
            result.setRuleCode(rule.getRuleCode());
            result.setRuleName(rule.getRuleName());
            result.setStartTime(startTime);
            result.setEndTime(new Date());
            result.setExecutionTime(result.getEndTime().getTime() - startTime.getTime());
            result.setTraceId(traceId);
            result.setInputData(request.getInputData());
            result.setContext(request.getContext());
            result.setUsedCache(false);

            // 缓存结果
            if (Boolean.TRUE.equals(request.getUseCache()) && result.getStatus().equals(RuleExecuteStatusEnum.SUCCESS.getCode())) {
                cacheResult(request, result);
            }

            // 记录执行日志
            if (Boolean.TRUE.equals(request.getLogExecution())) {
                logExecution(result);
            }

            return result;

        } catch (Exception e) {
            log.error("规则执行异常: {}", rule.getRuleCode(), e);
            return createErrorResult(rule.getRuleCode(), rule.getRuleName(),
                RuleExecuteStatusEnum.ERROR, "规则执行异常: " + e.getMessage(), startTime, traceId, request);
        }
    }

    @Override
    public List<RuleExecuteResultVO> executeRules(List<String> ruleCodes, RuleExecuteRequestDTO request) {
        return ruleCodes.stream()
                .map(ruleCode -> {
                    RuleExecuteRequestDTO singleRequest = new RuleExecuteRequestDTO();
                    singleRequest.setRuleCode(ruleCode);
                    singleRequest.setInputData(request.getInputData());
                    singleRequest.setContext(request.getContext());
                    singleRequest.setUseCache(request.getUseCache());
                    singleRequest.setLogExecution(request.getLogExecution());
                    return executeRule(singleRequest);
                })
                .collect(Collectors.toList());
    }

    @Override
    public String validateRuleSyntax(String ruleContent, String engineType) {
        RuleEngine engine = engineRegistry.get(engineType);
        if (engine == null) {
            return "不支持的规则引擎类型: " + engineType;
        }
        return engine.validateRuleSyntax(ruleContent, engineType);
    }

    @Override
    public void registerEngine(RuleEngine engine) {
        String engineType = engine.getSupportedEngineType();
        RuleEngine existingEngine = engineRegistry.get(engineType);
        
        if (existingEngine == null || engine.getPriority() > existingEngine.getPriority()) {
            engineRegistry.put(engineType, engine);
            log.info("注册规则引擎: {} (优先级: {})", engineType, engine.getPriority());
        }
    }

    @Override
    public List<String> getSupportedEngineTypes() {
        return new ArrayList<>(engineRegistry.keySet());
    }

    @Override
    public void clearCache(String ruleCode) {
        if (ruleCode == null) {
            executionCache.clear();
            log.info("清除所有规则执行缓存");
        } else {
            executionCache.entrySet().removeIf(entry -> entry.getKey().contains(ruleCode));
            log.info("清除规则缓存: {}", ruleCode);
        }
    }

    // ===== 私有辅助方法 =====

    /**
     * 生成追踪ID
     */
    private String generateTraceId() {
        return "RULE_" + System.currentTimeMillis() + "_" + Thread.currentThread().getId();
    }

    /**
     * 生成缓存键
     */
    private String generateCacheKey(RuleExecuteRequestDTO request) {
        StringBuilder keyBuilder = new StringBuilder();
        keyBuilder.append(request.getRuleCode());
        
        if (request.getInputData() != null) {
            // 简化实现，实际应该对Map进行有序序列化
            keyBuilder.append("_").append(request.getInputData().hashCode());
        }
        
        if (request.getContext() != null) {
            keyBuilder.append("_").append(request.getContext().hashCode());
        }
        
        return keyBuilder.toString();
    }

    /**
     * 推断引擎类型
     */
    private String inferEngineType(ParamRule rule) {
        // 简化实现：根据规则内容特征推断引擎类型
        // 实际项目中应该在规则中明确指定引擎类型
        
        if (rule.getConditionExpression() != null) {
            String condition = rule.getConditionExpression().toLowerCase();
            if (condition.contains("def ") || condition.contains("groovy")) {
                return "GROOVY";
            } else if (condition.matches(".*\\^.*\\$.*") || condition.contains("Pattern")) {
                return "REGEX";
            } else if (condition.contains("#{") || condition.contains("T(")) {
                return "SPEL";
            }
        }
        
        // 默认使用SpEL引擎
        return "SPEL";
    }

    /**
     * 转换VO为POJO
     */
    private ParamRule convertToParamRule(ParamRuleVO vo) {
        ParamRule rule = new ParamRule();
        rule.setId(vo.getId());
        rule.setRuleCode(vo.getRuleCode());
        rule.setRuleName(vo.getRuleName());
        rule.setRuleType(vo.getRuleType());
        rule.setDescription(vo.getDescription());
        rule.setPriority(vo.getPriority());
        rule.setIsActive(vo.getStatus());
        
        // 简化处理：将规则内容放到conditionExpression中
        rule.setConditionExpression(vo.getRuleContent());
        
        return rule;
    }

    /**
     * 创建错误结果
     */
    private RuleExecuteResultVO createErrorResult(String ruleCode, String ruleName, 
                                                 RuleExecuteStatusEnum status, String message,
                                                 Date startTime, String traceId, RuleExecuteRequestDTO request) {
        RuleExecuteResultVO result = new RuleExecuteResultVO();
        result.setRuleCode(ruleCode);
        result.setRuleName(ruleName);
        result.setStatus(status.getCode());
        result.setMessage(message);
        result.setStartTime(startTime);
        result.setEndTime(new Date());
        result.setExecutionTime(result.getEndTime().getTime() - startTime.getTime());
        result.setTraceId(traceId);
        result.setInputData(request.getInputData());
        result.setContext(request.getContext());
        result.setUsedCache(false);
        return result;
    }

    /**
     * 缓存执行结果
     */
    private void cacheResult(RuleExecuteRequestDTO request, RuleExecuteResultVO result) {
        try {
            String cacheKey = generateCacheKey(request);
            // 默认缓存300秒
            long ttl = 300L;
            
            CacheEntry cacheEntry = new CacheEntry(cloneResult(result), ttl);
            executionCache.put(cacheKey, cacheEntry);
            
            result.setCacheKey(cacheKey);
            log.debug("缓存规则执行结果: {}", request.getRuleCode());
        } catch (Exception e) {
            log.warn("缓存规则执行结果失败: {}", request.getRuleCode(), e);
        }
    }

    /**
     * 克隆执行结果
     */
    private RuleExecuteResultVO cloneResult(RuleExecuteResultVO original) {
        RuleExecuteResultVO cloned = new RuleExecuteResultVO();
        cloned.setRuleCode(original.getRuleCode());
        cloned.setRuleName(original.getRuleName());
        cloned.setStatus(original.getStatus());
        cloned.setResultData(original.getResultData());
        cloned.setMessage(original.getMessage());
        cloned.setErrorCode(original.getErrorCode());
        cloned.setErrorDetail(original.getErrorDetail());
        cloned.setExecutionTime(original.getExecutionTime());
        return cloned;
    }

    /**
     * 记录执行日志
     */
    private void logExecution(RuleExecuteResultVO result) {
        // 这里应该记录到数据库或日志系统
        // 简化实现：只记录到应用日志
        log.info("规则执行完成 - 规则: {}, 状态: {}, 耗时: {}ms, 追踪ID: {}", 
                result.getRuleCode(), result.getStatus(), result.getExecutionTime(), result.getTraceId());
    }
}
